package ee.ut.maxorato_macobo.oop.mud.game;

import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Random;

import ee.ut.maxorato_macobo.oop.mud.items.ContainsItems;
import ee.ut.maxorato_macobo.oop.mud.items.ItemBase;
import ee.ut.maxorato_macobo.oop.mud.items.ItemCorpse;
import ee.ut.maxorato_macobo.oop.mud.items.ItemTemplate;
import ee.ut.maxorato_macobo.oop.mud.items.ItemTemplatePool;

public class NpcCharacter extends GameCharacter {
	private NpcTemplate npcTemplate;
	private NpcLoader npcLoader;
	private boolean isDead;
	private Random randGen;
	
	public NpcCharacter(GameRoom newStartRoom, NpcTemplate newNpcTemplate, NpcLoader newNpcLoader) {
		super(null);
		
		randGen = new Random(System.nanoTime());
		
		isDead = false;
		
		npcTemplate = newNpcTemplate;
		npcLoader = newNpcLoader;
		
		currentEnergy = getMaxEnergy();
		currentMana = getMaxMana();
		currentHealth = getMaxHealth();
		
		moveToRoom(newStartRoom, null);
	}
	
	public void describeForPlayer(PlayerCharacter player) {
		player.sendTickMessage("NPC '" + npcTemplate.getNpcName() + "': " + npcTemplate.getNpcDescription());
		
		player.sendTickMessage("This NPC is carrying: ");
		GameUtils.describeItemListForPlayer(player, getItemList(), false);
	}
	
	public NpcTemplate getTemplate() {
		return npcTemplate;
	}
	
	public NpcLoader getLoader() {
		return npcLoader;
	}
	
	public void handleDeath(boolean defaultNotice) {
		fightTarget = null;
		
		npcLoader.instanceRemoved();
		currentRoom.characterLeftRoom(this, "void");
		NpcPool.unregisterNpc(this);
		
		if(defaultNotice) {
			ListIterator<PlayerCharacter> it = currentRoom.getRoomPlayerList().listIterator();
			
			while(it.hasNext()) {
				it.next().sendTickMessage("NPC " + getCharName() + " died.");
			}
		}
		
		ItemTemplate corpseTemplate = ItemTemplatePool.findByUniqueName("corpse");
		
		if(corpseTemplate != null) {
			ItemBase corpse = corpseTemplate.createInstance(currentRoom);
			
			if(corpse instanceof ContainsItems) {
				ArrayList<ItemBase> itemList = new ArrayList<ItemBase>(getItemList());
				
				for(ItemBase item : itemList) {
					item.moveToLocation((ContainsItems)corpse);
				}
			}
			
			if(corpse instanceof ItemCorpse) {
				int customCrumbleTime = getTemplate().getCrumbleTime();
				
				if(customCrumbleTime >= 0) {
					((ItemCorpse)corpse).setCrumbleTime(customCrumbleTime);
				}
				
				((ItemCorpse)corpse).lockCorpse();
			}
			
			corpse.setCustomDescription("This corpse belongs to " + getTemplate().getNpcDescription() + ".");
		}
		
		isDead = true;
	}
	
	public int getNumberOfHits(GameCharacter target) {
		return (int)(Math.floor(randGen.nextInt(5) / 4)) + 1;
	}
	
	public boolean isAlive(int lifeCycleIndex) {
		return !isDead; 
	}
	
	public int getLifeCycleIndex() {
		return 1;
	}
	
	public boolean hasAutoRetaliate() {
		return true;
	}
	
	public String getCharName() {
		return npcTemplate.getNpcName();
	}
	
	public int getMaxEnergy() {
		return npcTemplate.getMaxEnergy();
	}
	
	public int getMaxMana() {
		return npcTemplate.getMaxMana();
	}
	
	public int getMaxHealth() {
		return npcTemplate.getMaxHealth();
	}

	public void processTick() {
		validateFight();
		
		if(fightTarget == null) {
			Random randGen = new Random(System.nanoTime());
			
			if(randGen.nextInt(1000) < npcLoader.getMoveFreq()) {
				String[] exitList = currentRoom.getExitListString().split(", ");
				
				if(exitList.length > 0 && exitList[0].length() > 0) {
					String exitName = exitList[randGen.nextInt(exitList.length)];
					GameRoom target = currentRoom.getExitAtDir(exitName);
					
					if(target != null) {
						moveToRoom(target, exitName);
					}
				}
			}
		}
	}
}
